<template>
  <div id="viewer" ref="viewerContainer"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';
import { Viewer, utils } from '@photo-sphere-viewer/core';
import type { PluginConstructor } from '@photo-sphere-viewer/core';
import { MarkersPlugin } from '@photo-sphere-viewer/markers-plugin';
import { GalleryPlugin } from '@photo-sphere-viewer/gallery-plugin';
import { AutorotatePlugin } from '@photo-sphere-viewer/autorotate-plugin';

import type { Tooltip } from '@photo-sphere-viewer/core';
import type { MarkerConfig } from '@photo-sphere-viewer/markers-plugin';

import '@photo-sphere-viewer/core/index.css';
import '@photo-sphere-viewer/markers-plugin/index.css';
import '@photo-sphere-viewer/gallery-plugin/index.css';

import type { Marker, PhotoItem } from '@/pages/scene/photos';

interface NormalizedPosition {
  yaw: number;
  pitch: number;
}

const props = defineProps<{
  hasAnimate?: boolean;
  imgList: PhotoItem[];
  hasGallery?: boolean;
  initialYaw?: number | string;
  initialPitch?: number | string;
  initialZoom?: number;
  initialFisheye?: number;
  animationDuration?: number;
  animationEasing?: string;
}>();

const emit = defineEmits(['selectMarker', 'viewerClick', 'markerUpdated']);

const viewerContainer = ref<HTMLElement | null>(null);
let viewer: Viewer | null = null;
let markersPlugin: MarkersPlugin | null = null;
let autorotatePlugin: AutorotatePlugin | null = null;
let galleryPlugin: GalleryPlugin | null = null;

const panoramaUrl = ref<string>('');
const currIndex = ref<number>(0);

// --- Methods ---

const initViewer = () => {
  if (!viewerContainer.value) {
    console.error('未找到 Viewer 容器。');
    return;
  }

  if (props.imgList.length === 0) {
    console.error('imgList 为空，无法初始化 Viewer。');
    return;
  }
  panoramaUrl.value = props.imgList.at(0)?.panorama || '';
  const initialPhoto = props.imgList.at(0);

  // 修正：直接构建并明确类型
  const plugins: (PluginConstructor | [PluginConstructor, any])[] = [
    [
      AutorotatePlugin,
      {
        autostartDelay: null,
        autorotateSpeed: '1rpm',
      },
    ],
    [
      MarkersPlugin,
      {
        markers: [],
        defaultMarkerConfig: {
          draggable: true,
        },
      },
    ],
  ];

  if (props.hasGallery) {
    plugins.push([
      GalleryPlugin,
      {
        visibleOnLoad: true,
        hideOnClick: false,
      },
    ]);
  }

  viewer = new Viewer({
    container: viewerContainer.value,
    panorama: panoramaUrl.value,
    caption: initialPhoto?.options?.caption || '全景查看器',
    loadingImg: '/images/loader.png',
    touchmoveTwoFingers: true,
    mousewheelCtrlKey: false,
    navbar: [
      'autorotate',
      'zoom',
      'markers',
      'move',
      'download',
      ...(props.hasGallery ? ['gallery'] : []),
      {
        title: '更改点位',
        content: '🔄',
        onClick: randomPoints,
      },
      'caption',
      'fullscreen',
    ],
    plugins,
    defaultYaw: initialPhoto?.initialView?.yaw || props.initialYaw || 0,
    defaultPitch: initialPhoto?.initialView?.pitch || props.initialPitch || 0,
    defaultZoomLvl: initialPhoto?.initialView?.zoom || props.initialZoom || 50,
    fisheye: initialPhoto?.initialView?.fisheye || props.initialFisheye || 0,
  });

  markersPlugin = viewer.getPlugin(MarkersPlugin) as MarkersPlugin;
  autorotatePlugin = viewer.getPlugin(AutorotatePlugin) as AutorotatePlugin;
  galleryPlugin = viewer.getPlugin(GalleryPlugin) as GalleryPlugin;


  if (props.hasGallery && galleryPlugin) {
    galleryPlugin.setItems(props.imgList.map(item => ({
      id: item.id,
      panorama: item.panorama,
      thumbnail: item.thumbnail,
      name: item.name,
      options: item.options,
    })));
  }

  viewer.addEventListener('click', (event: any) => {
    emit('viewerClick', {
      yaw: event.data.yaw,
      pitch: event.data.pitch,
      rightclick: event.data.rightclick,
    });
  });

  viewer.addEventListener('ready', handleViewerReady, { once: true });
};

const addDragListenersToMarkers = () => {
  nextTick(() => {
    // 确保 markersPlugin 已加载且容器存在
    if (markersPlugin && viewerContainer.value) {
      // 获取所有标记的 DOM 元素
      const markerElements = viewerContainer.value.querySelectorAll('.psv-marker');

      markerElements.forEach((markerElement) => {
        // 将 Element 类型断言为 HTMLElement
        const htmlElement = markerElement as HTMLElement;
        const markerId = htmlElement.dataset.psvMarkerId;

        // 确保 markerId 存在
        if (markerId && markersPlugin) {

          const marker = markersPlugin.getMarker(markerId);

          // 检查标记是否存在且可拖动
          // 这里的类型断言 (marker.config as any) 是为了解决 TypeScript 报错
          if (marker && (marker.config as any).draggable) {
            // 阻止鼠标事件冒泡
            htmlElement.addEventListener('mousedown', (e) => e.stopPropagation());
            // 阻止触屏事件冒泡
            htmlElement.addEventListener('touchstart', (e) => e.stopPropagation());
          }
        }
      });
    }
  });
};

const handleViewerReady = () => {
  if (markersPlugin) {
    const initialMarkers = props.imgList.at(currIndex.value)?.markers;
    markersPlugin.setMarkers(initialMarkers as MarkerConfig[] || []);
  }
  showInitMarker();
  if (props.hasAnimate) {
    enteraAimation();
  }

  // Viewer 初始加载后，给标记添加事件监听
  addDragListenersToMarkers();

};



const showInitMarker = () => {
  if (viewer && autorotatePlugin && markersPlugin) {
    const currentPhoto = props.imgList.at(currIndex.value);
    viewer
      .animate({
        yaw: currentPhoto?.initialView?.yaw || props.initialYaw || '-27deg',
        pitch: currentPhoto?.initialView?.pitch || props.initialPitch || '-6deg',
        speed: 100,
      })
      .then(() => {
        const initialMarkers = props.imgList.at(currIndex.value)?.markers;
        if (initialMarkers && initialMarkers.some(m => m.id === 'new-marker1')) {
          markersPlugin!.showMarkerTooltip('new-marker1');
        }
      });
  }
};

const clearMarker = () => {
  markersPlugin?.clearMarkers();
};

const updateMarker = (id: string, newProps: Partial<MarkerConfig>) => {
  markersPlugin?.updateMarker({
    id: id,
    ...newProps,
  });
};

const removeMarker = (id: string) => {
  markersPlugin?.removeMarker(id);
};

const updateIndex = (index: number) => {
  if (currIndex.value === index) {
    console.log('已经显示当前全景图，无需切换。');
    return;
  }
  currIndex.value = index;
  panoramaUrl.value = props.imgList.at(index)?.panorama || '';
  handelChangeViewer();
};

const handleSelectMarker = () => {
  markersPlugin?.addEventListener('select-marker', ({ marker }) => {
    emit('selectMarker', marker as Marker);
  });
};

const handleHoverMarker = () => {
  markersPlugin?.addEventListener('enter-marker', ({ marker }) => {
    // console.log("进入", marker.id);
  });
};

const handleLeaveMarker = () => {
  markersPlugin?.addEventListener('leave-marker', ({ marker }) => {
    // console.log("离开", marker.id);
  });
};

const handleMarkerDrag = () => {
  (markersPlugin?.addEventListener as any)('marker-position-updated', (event: any) => {
    emit('markerUpdated', {
      id: event.marker.id,
      position: { yaw: event.position.yaw, pitch: event.position.pitch },
      fullMarker: event.marker ? { ...event.marker } : undefined,
    });
  });
};


const handleGalleryChange = () => {
  document.addEventListener('click', (e) => {
    const element = e.target as HTMLElement;
    let sIndex = -1;

    let galleryItemElement: HTMLElement | null = null;
    if (element && element.dataset && element.dataset.psvGalleryItem) {
      galleryItemElement = element;
    } else if (element) {
      galleryItemElement = element.closest('[data-psv-gallery-item]') as HTMLElement;
    }

    if (galleryItemElement && galleryItemElement.dataset && galleryItemElement.dataset.psvGalleryItem) {
      const id = galleryItemElement.dataset.psvGalleryItem;
      sIndex = props.imgList.findIndex((data) => data.id === id);

      if (sIndex !== -1 && currIndex.value !== sIndex) {
        updateIndex(sIndex);
      } else if (sIndex === currIndex.value) {
        console.log('点击了当前全景图，无需切换。');
      }
    }
  });
};

const handelGalleryActive = () => {
  nextTick(() => {
    const galleryBox = document.querySelector('.psv-gallery-container');
    if (galleryBox) {
      galleryBox.querySelectorAll('.psv-gallery-item').forEach((item) => {
        const itemId = item.getAttribute('data-psv-gallery-item');
        if (props.imgList.at(currIndex.value) && itemId === props.imgList.at(currIndex.value)?.id) {
          item.classList.add('psv-gallery-item--active');
        } else {
          item.classList.remove('psv-gallery-item--active');
        }
      });
    }
  });
};

const handelChangeViewer = () => {
  if (viewer && markersPlugin) {
    clearMarker();
    handelGalleryActive();

    const currentPhoto = props.imgList.at(currIndex.value);
    viewer.setPanorama(panoramaUrl.value, {
      caption: currentPhoto?.options?.caption || '全景查看器',
      position: {
        yaw: currentPhoto?.initialView?.yaw || props.initialYaw || 0,
        pitch: currentPhoto?.initialView?.pitch || props.initialPitch || 0,
      },
    }).then(() => {
      viewer!.zoom(currentPhoto?.initialView?.zoom || props.initialZoom || 50);

      markersPlugin!.setMarkers(currentPhoto?.markers as MarkerConfig[] || []);
      console.log(`全景图切换成功，当前标记数量：${currentPhoto?.markers ? currentPhoto.markers.length : 0}`);

      // ==== 重点：在全景图和标记都加载完毕后调用新方法 ====
      addDragListenersToMarkers();

    }).catch(error => {
      console.error('切换全景图失败:', error);
    });
  }
};


const addMarkerDirectly = (markerData: Marker) => {
  if (markersPlugin) {
    const newMarker: MarkerConfig = {
      ...markerData,
      id: '#' + Math.random().toString(36).substr(2, 9),
      draggable: true,
    } as MarkerConfig;

    markersPlugin.addMarker(newMarker);
    console.log(`Marker ${newMarker.id} 已直接添加到 PhotoSphereViewer。`);

    const finalPosition = newMarker.position as NormalizedPosition;
    emit('markerUpdated', {
      id: newMarker.id,
      position: { yaw: finalPosition.yaw, pitch: finalPosition.pitch },
      fullMarker: newMarker,
    });
  }
};

const handelListenerViewerClick = (markerData: Marker) => {
  console.warn("handelListenerViewerClick is deprecated for direct marker addition. Use addMarkerDirectly instead.");
};

const randomPoints = () => {
  markersPlugin?.showAllTooltips();
};

const enteraAimation = () => {
  if (!viewer) return;

  const currentPhoto = props.imgList.at(currIndex.value);
  const animDuration = currentPhoto?.animation?.duration || props.animationDuration || 2500;
  const animEasing = currentPhoto?.animation?.easing || props.animationEasing || 'inOutQuad';

  const animProps = {
    pitch: {
      start: -Math.PI / 2,
      end: currentPhoto?.initialView?.pitch ? utils.parseAngle(currentPhoto.initialView.pitch as string) : (props.initialPitch !== undefined ? utils.parseAngle(props.initialPitch as string) : 0.2)
    },
    yaw: {
      start: Math.PI,
      end: currentPhoto?.initialView?.yaw ? utils.parseAngle(currentPhoto.initialView.yaw as string) : (props.initialYaw !== undefined ? utils.parseAngle(props.initialYaw as string) : 0)
    },
    zoom: {
      start: 0,
      end: currentPhoto?.initialView?.zoom || props.initialZoom || 50
    },
    fisheye: {
      start: currentPhoto?.initialView?.fisheye || props.initialFisheye || 2,
      end: 0
    },
  };

  new utils.Animation({
    properties: animProps,
    duration: animDuration,
    easing: animEasing,
    onTick: (properties) => {
      viewer?.setOption('fisheye', properties.fisheye);
      viewer?.rotate({ yaw: properties.yaw, pitch: properties.pitch });
      viewer?.zoom(properties.zoom);
    },
  }).then(() => {
    if (props.hasGallery && galleryPlugin) {
      galleryPlugin.setItems(props.imgList.map(item => ({
        id: item.id,
        panorama: item.panorama,
        thumbnail: item.thumbnail,
        name: item.name,
        options: item.options,
      })));
    }
  });
};

defineExpose({
  updateIndex,
  updateMarker,
  removeMarker,
  handelChangeViewer,
  handelListenerViewerClick,
  addMarkerDirectly,
  getCurrentPhotoIndex: () => currIndex.value,
});

onMounted(() => {
  nextTick(() => {
    if (viewerContainer.value) {
      initViewer();
      handleSelectMarker();
      handleHoverMarker();
      handleLeaveMarker();
      handleGalleryChange();
      handleMarkerDrag();
    }
  });
});

onBeforeUnmount(() => {
  if (viewer) {
    viewer.destroy();
    viewer = null;
    markersPlugin = null;
    autorotatePlugin = null;
    galleryPlugin = null;
  }
});

watch(
  () => props.imgList,
  (newVal, oldVal) => {
    if (viewer && newVal.length > 0 && newVal !== oldVal) {
      if (galleryPlugin) {
        galleryPlugin.setItems(newVal.map(item => ({
          id: item.id,
          panorama: item.panorama,
          thumbnail: item.thumbnail,
          name: item.name,
          options: item.options,
        })));
      }
      handelChangeViewer();
    }
  }, { deep: true }
);
</script>

<style lang="scss" scoped>
#viewer {
  width: 100%;
  height: 100%;
  background-color: #f0f0f0;
}
</style>